package com.example.batch.core.loadbalance.strategy;

import com.example.batch.core.loadbalance.DataSourceWrapper;
import com.example.batch.core.loadbalance.LoadBalanceStrategy;
import com.example.batch.core.loadbalance.NoAvailableDataSourceException;
import com.example.batch.core.metrics.MetricsCollector;
import org.springframework.stereotype.Component;

import java.util.Comparator;
import java.util.List;

/**
 * 最少连接数负载均衡策略
 * 选择当前活动连接数最少的数据源
 */
@Component
public class LeastConnectionStrategy implements LoadBalanceStrategy {
    
    // 指标收集器,用于获取连接数信息
    private final MetricsCollector metricsCollector;
    
    @Override
    public DataSource select(List<DataSourceWrapper> dataSources) {
        // 查找活动连接数最少的数据源
        return dataSources.stream()
            .min(Comparator.comparingInt(ds -> 
                metricsCollector.getActiveConnections(ds.getName())))
            .map(DataSourceWrapper::getDataSource)
            .orElseThrow(() -> new NoAvailableDataSourceException("No data source available"));
    }
}

/**
 * 响应时间负载均衡策略
 * 根据数据源的平均响应时间和当前连接数综合评分选择
 */
@Component
public class ResponseTimeStrategy implements LoadBalanceStrategy {
    
    // 指标收集器
    private final MetricsCollector metricsCollector;
    // 响应时间权重因子(0-1之间)
    private final double weightFactor = 0.3;
    
    @Override
    public DataSource select(List<DataSourceWrapper> dataSources) {
        // 查找评分最低的数据源
        return dataSources.stream()
            .min(Comparator.comparingDouble(this::calculateScore))
            .map(DataSourceWrapper::getDataSource)
            .orElseThrow(() -> new NoAvailableDataSourceException("No data source available"));
    }
    
    /**
     * 计算数据源评分
     * 评分 = 响应时间 * 权重 + 活动连接数 * (1-权重)
     */
    private double calculateScore(DataSourceWrapper wrapper) {
        double avgResponseTime = metricsCollector.getAverageResponseTime(wrapper.getName());
        int activeConnections = metricsCollector.getActiveConnections(wrapper.getName());
        return avgResponseTime * weightFactor + activeConnections * (1 - weightFactor);
    }
} 